#pragma once
#include <libglew/glew.h>
#ifdef WIN32
#include <GL/glut.h>
#endif
#ifdef __APPLE__
#include <GLUT/glut.h>
#endif
#include "Camera.h"
#include "GLSLShaderProgram.h"
#include <iostream>
#include <sstream>

namespace lib3dw 
{
	typedef enum { Black, PointLight, SpotLight} LightType;

	class LightSource
	{
		public:
			LightSource();
			~LightSource();
			const GLfloat* GetPosition() const;
			const GLfloat* GetAmbient() const;
			const GLfloat* GetDiffuse() const;
			const GLfloat* GetSpecular() const;
			const GLenum GetLightNumber() const; // returns OpenGL light number (enum) !!! -> use GetTextureUnit to obtain zero-based, numeric LightNumber
			const GLuint GetTextureSlot() const;
			void SetPosition(float x, float y, float z, float w);
			void SetAmbient(float r, float g, float b, float a);
			void SetDiffuse(float r, float g, float b, float a);
			void SetSpecular(float r, float g, float b, float a);
			void SetLightNumber(GLenum number);
			void InitShadowMap(Camera* newCamera, GLSLShaderProgram* newProgram, int newTextureSlot);
			void UpdateShadowMap(void (*DrawMethod)());
			GLuint GetShadowProgramId();
			GLuint GetShadowProgramUniformTextureUnitId();
			GLuint GetShadowMapTextureId();
			virtual LightType GetLightType() = 0;
			virtual int GetShadowMapSize() = 0;

		protected:
			GLfloat* position;
			GLfloat* ambient;
			GLfloat* diffuse;
			GLfloat* specular;
			GLenum lightNumber;
			GLuint* shadowMapTextureId;
			GLuint shadowMapUniformId;
			GLuint fboId;
			GLSLShaderProgram* shadowProgram;
			Camera* camera;
			float*lightProjMat;
			float* lightViewMat;
			float* camProjMat;
			float* camViewMat;
			
		private:
			void CreateFBODepthTexture();
			bool InvertCameraViewMatrix(float i[16], const float m[16]);
			void SetupTextureMatrix();
			void SetupCameraMatrices(Camera* camera);
			virtual void SetupLightMatrices() const = 0;;
			void CheckFramebufferStatus();
			void RenderFromLightPosition(void (*DrawMethod)());
			void RenderFromCameraPosition(Camera* camera, void (*DrawMethod)());	
			int textureSlot;	
	};
}